//////////////////////////////////////////
// PREDATOR CLASS						//
//////////////////////////////////////////
/**
 * Predators are moving repulsor emitters (that's how we get that nice dispersion effect which
 * looks like biods are running away!). Predators run around and chase the closest visible biod
 * (like biods, they only see what's in front of them). If a predator overlaps a biod, it "eats"
 * the biod, and the biod is removed from the simulation.
 */
class Predator {
    constructor(
        position,
        speed,
        turnSpeed,
        radius,
        sightRadius,
        scariness,
        presence,
        sandboxDimensions
    ) {
        this.position = position;
        this.speed = speed;
        this.turnSpeed = turnSpeed;
        this.radius = radius;
        this.sightRadius = sightRadius;
        this.scariness = scariness; //Strength of the repulsor emitter.
        this.presence = presence; //Radius of the repulsor emitter.

        this.sandboxDimensions = sandboxDimensions;

        this.emitter = new Emitter(
            this.position,
            this.scariness,
            this.presence,
            "exp",
            true
        );

        this.heading = new Vector(1, 0);
    }

    calculateNewHeading(flock) {
        if (flock.length == 0) return this.heading;

        var victim = null;
        var distanceToVictim = this.sightRadius + 1;

        //Find the closest biod - and chase it!
        for (var i = 0; i < flock.length; i++)
            if (
                flock[i].position.getDistance(this.position) < distanceToVictim
            ) {
                var cosDot = Math.cos(
                    this.heading.dot(
                        this.position.getDirectionTo(flock[i].position)
                    )
                ); //Make sure neighbor is in front of us.

                if (cosDot > 0) {
                    //Victim must be in front of us.
                    victim = flock[i];
                    distanceToVictim = victim.position.getDistance(
                        this.position
                    );
                }
            }

        //The case is on!
        if (victim != null)
            return this.position.getDirectionTo(victim.position);
        else return this.heading;
    }

    move(newHeading, flock) {
        var newAngle, currentAngle, left, right, rotationAmount;
        var positionOffset;

        //Attempt to rotate current heading to new heading. Limited rotation speed is important!
        newAngle = newHeading.toDegrees();
        currentAngle = this.heading.toDegrees();

        //Figure out if it's quicker to turn left or right.
        left = (newAngle - currentAngle + 360) % 360;
        right = (currentAngle - newAngle + 360) % 360;

        //Compute how much we need to turn, capped by max turn speed.
        rotationAmount =
            left < right
                ? Math.min(this.turnSpeed, left)
                : (rotationAmount = -Math.min(this.turnSpeed, right));

        //Turn.
        this.heading.fromDegrees((currentAngle + rotationAmount + 360) % 360);

        //Compute new position.
        positionOffset = this.heading.scale(this.speed);
        this.position.x =
            (this.position.x + positionOffset.x) % this.sandboxDimensions.x;
        this.position.y =
            (this.position.y + positionOffset.y) % this.sandboxDimensions.y;

        //Wrap around the sandbox.
        if (this.position.x < 0) this.position.x = this.sandboxDimensions.x;
        if (this.position.y < 0) this.position.y = this.sandboxDimensions.y;

        //Update the emitter.
        this.emitter.position = this.position;
        this.emitter.update(flock);
    }
}
export { Predator };
